#ifndef __RADIX_TREE__
#define __RADIX_TREE__

#include <linux/mount.h>
#include <linux/radix-tree.h>
#include <linux/version.h>
#include<linux/kallsyms.h>
#include<linux/sched.h>
#include<linux/pid_namespace.h>
#include<linux/mmzone.h>
#include<linux/nodemask.h>
#include<linux/mm.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 9)
#include<linux/page-flags.h>
#include<linux/slab.h>
#include<linux/slub_def.h>
#include<linux/types.h>
#include <linux/proc_fs.h>
#include <linux/memcontrol.h>
#include <linux/cgroup-defs.h>
#include <linux/kernfs.h>
#include <linux/page_counter.h>
#include <linux/vmalloc.h>
#else
#define LINUX_310
#include "memcontrol_7.h"
#endif

#define NAME_LEN (1024)
struct radix_item {
    unsigned long key;
};
struct mount {
        struct hlist_node mnt_hash;
        struct mount *mnt_parent;
        struct dentry *mnt_mountpoint;
        struct vfsmount mnt;
#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)
        union {
                struct rcu_head mnt_rcu;
                struct llist_node mnt_llist;
        };
#endif
#ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
#else
        int mnt_count;
        int mnt_writers;
#endif
        struct list_head mnt_mounts;    /* list of children, anchored here */
        struct list_head mnt_child;     /* and going through their mnt_child */
        struct list_head mnt_instance;  /* mount instance on sb->s_mounts */
};

struct inode_item {
    struct radix_item node;
    struct list_head inode;
    unsigned long i_ino;
    int nr_pages;
    int deleted:4;
    int shmem:4;
    unsigned long cached;
    char *filename;
};

struct file_item_list {
    struct list_head items_list;
    char filename[NAME_LEN];
    unsigned long  size;
    unsigned long  cached;
    int  deleted;
};

struct filecache_result_list {
    int num;
    char fsname[NAME_LEN];
    struct list_head file_items_list;
};

struct file_item {
    char filename[NAME_LEN];
    unsigned long  size;
    unsigned long  cached;
    int  deleted;
};

struct filecache_result {
    int num;
    char fsname[NAME_LEN];
    struct file_item *filecache_items;
};

typedef enum _memhunter_type {
    MEMHUNTER_CACHE_TYPE_FILE = 1,
    MEMHUNTER_CACHE_TYPE_MEMCG_DYING,
    MEMHUNTER_CACHE_TYPE_MEMCG_ONE,
} memhunter_type;

typedef void (*node_free_t)(void *args);

static inline bool  _IS_ERR(const void *ptr)
{
    if((unsigned long)ptr < 0xffff000000000000){
        return 1;
    }
    return IS_ERR_VALUE((unsigned long)ptr);
}
static inline int _page_is_file_cache(struct page *page)
{
    return !PageSwapBacked(page);
}

static inline int page_is_shmem(struct page *page)
{
   return !!(!_page_is_file_cache(page) && !PageAnon(page));
}
int prepend(char **buffer, int *buflen, const char *str, int namelen);
int scan_inode_name(struct inode *inode, char *buf, int len, unsigned long *cached, int *deleted);
void radix_init(struct radix_tree_root *root);
int radix_insert(struct radix_tree_root *root, unsigned long key, void *ptr);
void *radix_lookup(struct radix_tree_root *root, unsigned long key);
int radix_delete(struct radix_tree_root *root, unsigned long key);
int radix_delete_all(struct radix_tree_root *root, node_free_t free);
int filecache_scan(void);
int memcg_dying_scan(void);
int memcg_scan_one(void);
int filecache_main(unsigned long arg);
#ifdef LINUX_310
enum {
    CSS_DYING    = 0, /* this CSS is dying*/
};
#endif
#endif
